﻿using System;
using System.Threading;
using Microsoft.Practices.Unity;

namespace Yeap.Kernel.Unity
{
    public static class Global
    {
        private static readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
        private static readonly IUnityContainer _container = new UnityContainer();

        static Global()
        {
            _container.AddNewExtension<TypeTrackingExtension>();
        }

        public static void RegisterInstancePerThread<T>(T instance)
        {
            RegisterInstance(instance, new PerThreadLifetimeManager<T>());
        }

        public static void RegisterInstance<T>(T instance)
        {
            RegisterInstance(instance, new ContainerControlledLifetimeManager());
        }

        public static void RegisterInstance<T>(T instance, LifetimeManager lifetimeManager)
        {
            _rwLock.EnterWriteLock();
            try
            {
                _container.RegisterInstance(instance, lifetimeManager);
            }
            finally
            {
                _rwLock.ExitWriteLock();
            }
        }
        public static void RegisterTransientType<TFrom, TTo>() where TTo: TFrom
        {
            RegisterType<TFrom, TTo>(new TransientLifetimeManager());
        }
        public static void RegisterType<TFrom, TTo>() where TTo:TFrom
        {
            RegisterType<TFrom, TTo>(new ContainerControlledLifetimeManager());
        }
        public static void RegisterType<TFrom, TTo>(LifetimeManager lifetimeManager) where TTo:TFrom
        {
            _rwLock.EnterWriteLock();
            try
            {
                _container.RegisterType<TFrom, TTo>(lifetimeManager);
            }
            finally
            {
                _rwLock.ExitWriteLock();
            }
        }

        public static T Resolve<T>()
        {
            _rwLock.EnterReadLock();
            try
            {
                if (_container.Configure<TypeTrackingExtension>().CanResolve<T>())
                {
                    return _container.Resolve<T>();
                }
                return default(T);
            }
            finally
            {
                _rwLock.ExitReadLock();
            }
        }
    }
}